package com.lant.utils;

import java.net.URI;
import java.util.Map;
import java.util.Set;
import org.springframework.web.client.RestClientException;
import org.springframework.web.client.RestTemplate;
import com.lant.enums.ResponseStatusEnum;
import com.lant.pojo.LantResult;

public class HttpUtils {

    private static final String HTTP_ERROR = "http请求异常：{%s}";

    /**
     * 向指定微服务发送GET请求（注意占位符和参数的一一对应关系）
     * 
     * <pre>
     * 传入url：
     * String url ="http://sm-provider/tProvince/preSave?code={1}&company={2}"
     * 
     * 传入参数：
     * 8888, "公司"
     * 
     * 替换占位符数值后的请求地址：
     *  http://sm-provider/tProvince/preSave?code="8888"&company="公司"
     * </pre>
     * 
     * @param restTemplate 负载均衡接口调度器
     * @param url 请求链接(包含占位符)
     * @param params 参数
     * @return LantResult标准接口返回对象
     */
    public static LantResult get(RestTemplate restTemplate, String url, Object... params) {
        try {
            return restTemplate.getForObject(url, LantResult.class, params);
        } catch (RestClientException e) {
            return LantResult.build(ResponseStatusEnum.BAD_REQUEST.getValue(),
                String.format(HTTP_ERROR, e.getMessage()));
        }
    }

    /**
     * 向指定微服务发送GET请求
     * 
     * <pre>
     * 传入url：
     * String url ="http://sm-provider/tProvince/preSave"
     * 
     * 传入参数：
     * Map<String, Object> params = new HashMap<>()
     * params.put("code", 8888)
     * params.put("company", "公司")
     * 
     * 最后请求地址(预处理)：
     * http://sm-provider/tProvince/preSave?code={code}&company={company}
     * 替换占位符数值后的请求地址：
     * http://sm-provider/tProvince/preSave?code="8888"&company="公司"
     * </pre>
     * 
     * @param restTemplate 负载均衡接口调度器
     * @param url 不含参数的请求链接
     * @param params 参数(占位符和url参数名都是使用map的键)
     * @return LantResult标准接口返回对象
     */
    public static LantResult get(RestTemplate restTemplate, String url, Map<String, Object> params) {
        try {
            return restTemplate.getForObject(addPlaceholderForGet(url, params), LantResult.class, params);
        } catch (RestClientException e) {
            return LantResult.build(ResponseStatusEnum.BAD_REQUEST.getValue(),
                String.format(HTTP_ERROR, e.getMessage()));
        }
    }

    /**
     * 向指定微服务发送GET请求
     * 
     * @param restTemplate 负载均衡接口调度器
     * @param uri java.net.URI(URI的构建参见JDK源码)
     * @return LantResult标准接口返回对象
     */
    public static LantResult get(RestTemplate restTemplate, URI uri) {
        try {
            return restTemplate.getForObject(uri, LantResult.class);
        } catch (RestClientException e) {
            return LantResult.build(ResponseStatusEnum.BAD_REQUEST.getValue(),
                String.format(HTTP_ERROR, e.getMessage()));
        }
    }

    /**
     * 向指定微服务发送POST请求
     * 
     * @param restTemplate 负载均衡接口调度器
     * @param url 请求链接
     * @param request 对象参数
     * @return LantResult标准接口返回对象
     */
    public static LantResult post(RestTemplate restTemplate, String url, Object request) {
        try {
            return restTemplate.postForObject(url, request, LantResult.class);
        } catch (RestClientException e) {
            return LantResult.build(ResponseStatusEnum.BAD_REQUEST.getValue(),
                String.format(HTTP_ERROR, e.getMessage()));
        }
    }

    /**
     * 向指定微服务发送POST请求（注意占位符和参数的一一对应关系）
     * 
     * <pre>
     * 传入url：
     * String url ="http://sm-provider/tProvince/preSave?code={1}&company={2}"
     * 
     * 传入参数：
     * 8888, "公司"
     * 
     * 替换占位符数值后的请求地址：
     *  http://sm-provider/tProvince/preSave?code="8888"&company="公司"
     * </pre>
     * 
     * @param restTemplate 负载均衡接口调度器
     * @param url 请求链接(包含占位符)
     * @param request 对象参数
     * @param params url后拼接参数
     * @return LantResult标准接口返回对象
     */
    public static LantResult post(RestTemplate restTemplate, String url, Object request, Object... params) {
        try {
            return restTemplate.postForObject(url, request, LantResult.class, params);
        } catch (RestClientException e) {
            return LantResult.build(ResponseStatusEnum.BAD_REQUEST.getValue(),
                String.format(HTTP_ERROR, e.getMessage()));
        }
    }

    /**
     * 向指定微服务发送POST请求
     * 
     * <pre>
     * 传入url：
     * String url ="http://sm-provider/tProvince/preSave"
     * 
     * 传入参数：
     * Map<String, Object> params = new HashMap<>()
     * params.put("code", 8888)
     * params.put("company", "公司")
     * 
     * 最后请求地址(预处理)：
     * http://sm-provider/tProvince/preSave?code={code}&company={company}
     * 替换占位符数值后的请求地址：
     * http://sm-provider/tProvince/preSave?code="8888"&company="公司"
     * </pre>
     * 
     * @param restTemplate 负载均衡接口调度器
     * @param url 不含参数的请求链接
     * @param request 对象参数
     * @param params url后拼接参数
     * @return LantResult标准接口返回对象
     */
    public static LantResult post(RestTemplate restTemplate, String url, Object request, Map<String, Object> params) {
        try {
            return restTemplate.postForObject(addPlaceholderForGet(url, params), request, LantResult.class, params);
        } catch (RestClientException e) {
            return LantResult.build(ResponseStatusEnum.BAD_REQUEST.getValue(),
                String.format(HTTP_ERROR, e.getMessage()));
        }
    }

    /**
     * 根据Map拼接请求链接的占位符(占位符和参数名都是使用map的键)
     * 
     * @param url 不含参数的请求链接
     * @param params 参数map
     * @return LantResult标准接口返回对象
     */
    private static String addPlaceholderForGet(String url, Map<String, Object> params) {
        if (params != null && !params.isEmpty()) {
            StringBuffer sb = new StringBuffer("?");
            Set<String> keySet = params.keySet();
            for (String key : keySet) {
                sb.append(key + "={" + key + "}&");
            }
            url = url + sb.substring(0, sb.length() - 1);
        }
        return url;
    }
}
